﻿using System;
using System.Collections.Generic;
using System.IO;
using PSE.Deployment.Engine.CustomExceptions;
using PSE.Deployment.Engine.Interfaces;
using PSE.Deployment.SetupBase.Configuration;
using PSE.Deployment.SetupBase.Parameter;
using Microsoft.Web.Administration;
using PSE.Deployment.SetupBase.Parameter.Enums;

namespace PSE.Deployment.SetupBase.Steps
{
    public class InstallWcfServiceMain : SetupStep<Configuration.Actions.InstallWcfServiceMain>
    {
        public InstallWcfServiceMain(IStepGroup parent, Group group, Configuration.Actions.InstallWcfServiceMain action, Parameter.Enums.SetupMode setupMode)
            : base(parent, group, action, setupMode)
        {
            this.ResetProgress(1);
        }

        public override void Execute()
        {
            this.ResetProgress(1);

            if (this.SetupMode == Parameter.Enums.SetupMode.Install)
            {
                InstallSite();
            }
            else if (this.SetupMode == Parameter.Enums.SetupMode.Uninstall)
            {
                UninstallSite();
            }
        }

        public override void Undo()
        {
            if (this.SetupMode == Parameter.Enums.SetupMode.Install)
            {
                UninstallSite();
            }
        }

        private void InstallSite()
        {
            using (ServerManager iisManager = new ServerManager())
            {
                string systemId = SetupMainFactory.GetInstance().Parameter.SetupConfiguration.SystemInfo.Id;

                this.IncrementProgress(systemId);

                ApplicationPool pool = iisManager.ApplicationPools[systemId];

                if (pool == null)
                {
                    pool = iisManager.ApplicationPools.Add(systemId);
                    pool.Enable32BitAppOnWin64 = true;
                    pool.ProcessModel.IdentityType = ProcessModelIdentityType.LocalSystem;
                }

                Site site = iisManager.Sites[systemId];

                if (site == null)
                {
                    site = iisManager.Sites.CreateElement("site");
                    site.Id = iisManager.Sites.Count + 1;
                    site.Name = systemId;
                    site.ServerAutoStart = true;
                    site.Bindings.Add(string.Format("*:{0}:", Action.HttpPort), "http");
                    site.Bindings.Add(string.Format("{0}:*", Action.TcpPort), "net.tcp");
                    site.Bindings.Add("*", "net.pipe");

                    Application application = site.Applications.CreateElement("application");
                    application.Path = "/";
                    application.ApplicationPoolName = systemId;
                    application.EnabledProtocols = "http,net.tcp,net.pipe";
                    application.VirtualDirectories.Add("/", Path.Combine(SetupMainFactory.GetInstance().Parameter.InstallationPath, systemId));
                    application.VirtualDirectories.Add("/" + systemId, Path.Combine(SetupMainFactory.GetInstance().Parameter.InstallationPath, Action.Folder.Destination));
                    site.Applications.Add(application);

                    iisManager.Sites.Add(site);

                }

                iisManager.CommitChanges();
            }
        }

        private void UninstallSite()
        {
            using (ServerManager iisManager = new ServerManager())
            {
                string systemId = SetupMainFactory.GetInstance().Parameter.SetupConfiguration.SystemInfo.Id;

                this.DecrementProgress(systemId);

                ApplicationPool pool = iisManager.ApplicationPools[systemId];

                if (pool != null)
                {
                    iisManager.ApplicationPools.Remove(pool);
                }

                Site site = iisManager.Sites[systemId];

                if (site != null)
                {
                    iisManager.Sites.Remove(site);
                }

                iisManager.CommitChanges();
            }
        }
    }
}
